﻿namespace System.Web.Mvc.Html
{
    using System;
    using System.ComponentModel;
    using System.Collections.Generic;
    using System.Data.Linq;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Linq.Expressions;
    using System.Text;
    using System.Web.Mvc.Resources;
    using System.Web.Routing;
    using jQuery.Validation.DataAnnotations;

    public static class jQueryValidationExtensions
    {

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString jQueryValidationFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            StringBuilder script = new StringBuilder();
            List<string> messages = new List<string>();
            List<string> validators = new List<string>();

            foreach (ModelValidator validator in ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).GetValidators(htmlHelper.ViewContext.Controller.ControllerContext))
            {
                    IEnumerable<ModelClientValidationRule> rules = validator.GetClientValidationRules();
                    foreach (var a in rules)
                    {
                        validators.Add(a.ValidationParameters["jQueryValidationInit"].ToString());
                        messages.Add(string.Format("{0}: \"{1}\"", a.ValidationParameters["jQueryName"].ToString(), a.ErrorMessage));
                    }
            }

            foreach(Attribute valAttr in ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).ContainerType.GetCustomAttributes(true))
            {
                if(valAttr.GetType().Equals(typeof(EqualToAttribute)))
                {
                    EqualToAttribute attr = (EqualToAttribute)valAttr;
                    ModelMetadata.FromLambdaExpression(model => model, htmlHelper.ViewData);
                    
                    EqualToValidator validator = new EqualToValidator(ModelMetadata.FromLambdaExpression(model => model, htmlHelper.ViewData), htmlHelper.ViewContext.Controller.ControllerContext, attr);
                    foreach (var a in validator.GetClientValidationRules())
                    {
                        if (ExpressionHelper.GetExpressionText(expression) == attr.SourceProperty)
                        {
                            validators.Add(a.ValidationParameters["jQueryValidationInit"].ToString());
                            messages.Add(string.Format("{0}: \"{1}\"", a.ValidationParameters["jQueryName"].ToString(), a.ErrorMessage));                            
                        }
                    }
                }
            }

            script.AppendFormat("$(\"#{0}\").rules(\"add\", {{", ExpressionHelper.GetExpressionText(expression));
            for (int i = 0; i < validators.Count; i++)
			{
			    script.AppendFormat("{0} ,", validators[i]);
			}

            script.Append("messages: {");
            for (int i = 0; i < messages.Count; i++)
			{
			    script.Append(messages[i]);
                if(i != messages.Count - 1)
                {
                    script.Append(",");
                }
			}

            script.Append("}});");

            return MvcHtmlString.Create(script.ToString());
        }

    }
}
